import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { CaslAbilityService } from 'src/auth/casl-ability.service';
import {
    CHECK_POLICIES_KEY,
    PolicyHandlerCallback,
    CaslHandlerType
} from 'src/decorators/casl.decarator';

@Injectable()
export class CaslGuard implements CanActivate {
    constructor(
        private reflector: Reflector,
        private caslAbilityService: CaslAbilityService,
    ) { }

    async canActivate(context: ExecutionContext): Promise<boolean> {
        // 1. 获取handlers 、canHandlers
        //  获取handlers
        const handlers = this.reflector.getAllAndMerge<PolicyHandlerCallback[]>(
            CHECK_POLICIES_KEY.HANDLER,
            [context.getHandler(), context.getClass()],
        );

        // 获取 canHandlers
        const canHandlers = this.reflector.getAllAndMerge<any[]>(
            CHECK_POLICIES_KEY.CAN,
            [context.getHandler(), context.getClass()],
        );

        // cannotHandlers
        const cannotHandlers = this.reflector.getAllAndMerge<any[]>(
            CHECK_POLICIES_KEY.CANNOT,
            [context.getHandler(), context.getClass()],
        );

        // 2. 初次判断 如果用户未设置 任一一个 直接返回true
        if (handlers.length === 0 || canHandlers.length === 0 || cannotHandlers.length === 0) {
            return true;
        }

        // 3. 接着获取http请求 检查用户是否存在
        // 3.1 如果有 handlers ，则检查每个 handler 对用户权限的处理结果，只有所有 handler 都返回 true ，flag 才保持为 true
        // 3.2 canHandlers ，根据其类型（数组或函数）进行类似的处理。
        // 3.3 cannotHandlers ，同样根据类型进行处理，如果任何一个 cannotHandler 返回 true ，则 flag 变为 false

        const req = context.switchToHttp().getRequest();

        if (req.user) {
            // 获取当前用户的权限
            const ability = await this.caslAbilityService.forRoot(req.user.username);

            let flag = true;
            if (handlers) {
                flag = flag && this.checkHandlers(handlers, ability);
            }
            if (flag && canHandlers) {
                flag = flag && this.checkCanHandlers(canHandlers, ability);
            }
            if (flag && cannotHandlers) {
                flag = flag && this.checkCannotHandlers(cannotHandlers, ability);
            }
            return flag;
        } else {

            return false;
        }
    }

    // 单独提取检查 handlers 的函数
    checkHandlers(handlers: PolicyHandlerCallback[], ability: any): boolean {
        return handlers.every((handler) => handler(ability));
    }

    // 单独提取检查 canHandlers 的函数
    checkCanHandlers(canHandlers: CaslHandlerType, ability: any): boolean {
        if (Array.isArray(canHandlers)) {
            return canHandlers.every((handler) => handler(ability));
        } else if (typeof canHandlers === 'function') {
            return canHandlers(ability);
        }
        return true; // 如果类型不符合预期，默认返回 true 以避免错误
    }

    // 单独提取检查 cannotHandlers 的函数
    checkCannotHandlers(cannotHandlers: CaslHandlerType, ability: any): boolean {
        if (Array.isArray(cannotHandlers)) {
            return cannotHandlers.every((handler) => handler(ability));
        } else if (typeof cannotHandlers === 'function') {

            console.log(cannotHandlers(ability));

            return cannotHandlers(ability);
        }
        return true; // 如果类型不符合预期，默认返回 true 以避免错误
    }
}
